/**
 * 
 */
package com.sebscape.sebcms.security.persistence;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

import javax.jdo.PersistenceManager;
import javax.jdo.Transaction;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.google.appengine.api.datastore.Key;
import com.sebscape.sebcms.persistence.PersistenceManagerFactoryWrapper;
import com.sebscape.sebcms.persistence.dao.GenericDao;
import com.sebscape.sebcms.security.domain.Group;
import com.sebscape.sebcms.security.domain.Role;
import com.sebscape.sebcms.security.domain.User;

/**
 * @author Stephen
 *
 */
public class UserDao extends GenericDao<User, Long> {

	private static Log log = LogFactory.getLog( UserDao.class );
	
	/**
	 * @param clazz
	 */
	public UserDao() {
		super( User.class );
	}

	
	/* (non-Javadoc)
	 * @see com.sebscape.sebcms.persistence.dao.GenericDao#load(java.io.Serializable)
	 */
	@Override
	public User load(Long id) {
		// load the user
		User nuser = null;
		PersistenceManager pm = PersistenceManagerFactoryWrapper.get().getPersistenceManager();
		Transaction tx = pm.currentTransaction();
		try {
			tx.begin();
			pm.getFetchPlan().addGroup( "extended_info" );
			User user = pm.getObjectById( persistentClass, id );
			// load up the collections.
			nuser = pm.detachCopy( user );
			log.debug( "nuser.getDemographic() = " + nuser.getDemographic() );
		} catch (Exception e) {
			e.printStackTrace();
			
		} finally {
			tx.commit();
			pm.close();
		}
		// TODO: This is a hack. Because Google does not init collections, we must fetch them manually.
		// I hope to remove this in the near future.
		if( nuser != null ){
			// populate the groups.
			initGroups(nuser);
			// populate the Roles.
			initRoles(nuser);
		}
		// return the user.
		return nuser;
	}
	
	public User findByUsername( String username ){
		return findByLogin( username, null );
	}
	
	@SuppressWarnings("unchecked")
	public User findByLogin( String username, String password ){
		PersistenceManager pm = PersistenceManagerFactoryWrapper.get().getPersistenceManager();
		Transaction tx = pm.currentTransaction();
		try {
			pm.getFetchPlan().addGroup( "extended_info" );
			String filter = "name==\'" + username + "\'";
			if( password != null ){
				filter += " && password==\'" + password + "\'";
			}
			tx.begin();
			List<User> result = (List<User>)pm.newQuery( persistentClass, filter ).execute();
			if( result != null && result.size() > 0 ){
				User user =  result.get( 0 );
				this.initGroups(user);
				this.initRoles(user);
				/*if ( user.getDemographic() != null ) {
					user.getDemographic().getLastname();
				} else {
					user.setDemographic( new Demographic() );
				}*/
				return user;
			} 
		} catch (Exception e) {
			e.printStackTrace();
			//throw new CmsPersistenceException( e.getCause().getMessage() + " jdoQL: " + jdoql );
		} finally {
			tx.commit();
			pm.close();
		}
		return null;
	}
	
	/**
	 * using the groupIdList values, fetch and set the list of Groups.
	 * @param user
	 */
	private void initGroups( User user ){
		log.debug("begin initGroups...");
		GroupDao dao = new GroupDao();
		user.setGroups( new ArrayList<Group>() );
		if( user.getGroupKeySet() == null ){
			log.debug( "groupKeySet was null...creating new/empty one.");
			user.setGroupKeySet( new HashSet<Key>() );
		}
		log.debug( "begin loop thru gorup keys...");
		for( Key gKey: user.getGroupKeySet() ){
			log.debug( "Loading key/id: " + gKey + " / " + gKey.getId() );
			Group g = (Group)dao.load( gKey.getId() );
			if( g != null ){ // this could happen if group was deleted.
				log.debug( "Added group: " + g.getName() );
				user.getGroups().add( g );
			}
		}
	}

	/**
	 * using the roleIdList values, fetch and set the list of Roles.
	 * @param user
	 */
	private void initRoles( User user ){
		RoleDao dao = new RoleDao();
		user.setRoles( new ArrayList<Role>() );
		if( user.getRoleKeySet() == null ){
			user.setRoleKeySet( new HashSet<Key>() );
		}
		for( Key rKey: user.getRoleKeySet() ){
			Role r = (Role)dao.load( rKey.getId() );
			if( r != null ){ // this could happen if group was deleted.
				user.getRoles().add( r );
			}
		}
		
	}
	

	/* (non-Javadoc)
	 * @see com.sebscape.sebcms.persistence.dao.GenericDao#save(java.lang.Object)
	 */
	@Override
	public User save(User user) {
		// TODO: update the Group.userKeyList.
		// TODO: update the Role.userKeyList.
		if( user.getGroupKeySet() == null ){
			log.debug("AT SAVE TIME...the groupKeySet: NULL" );
		} else {
			log.debug("AT SAVE TIME...the groupKeySet: " + user.getGroupKeySet().size());	    			
		}
		return super.save( user );
	}


	/* (non-Javadoc)
	 * @see com.sebscape.sebcms.persistence.dao.GenericDao#update(java.lang.Object)
	 */
	@Override
	public User update(User user) {
		// TODO: update the Group.userKeyList.
		// TODO: update the Role.userKeyList.
		// TODO: this is a hack so nobody changes 'admin' nor 'member' accounts.
		if( !user.getName().equalsIgnoreCase("admin") &&
			!user.getName().equalsIgnoreCase("member") ){
			return super.update( user );
		} else {
			return user;
		}
	}

}
